#include <iostream>
#include <string>

#if 0
#include <variant>
using std::variant;
using std::get;
using std::holds_alternative;
using std::bad_variant_access;
#else
#include <boost/variant2/variant.hpp>
using boost::variant2::variant;
using boost::variant2::get;
using boost::variant2::holds_alternative;
using boost::variant2::bad_variant_access;
#endif

#include <assert.h>


int main()
{
    using variant_ifd = variant<int, float, double>;
    variant_ifd v_i = 1;
    std::cout << get<int>(v_i) << std::endl;
    variant_ifd v_f =  1.1f;
    std::cout << get<float>(v_f) << std::endl;
    v_f = 1.2d;
    std::cout << get<double>(v_f) << std::endl;


    variant<int, float> v, w;
    v = 42; // v contains int
    int i = get<int>(v);
    assert(42 == i); // succeeds
    w = get<int>(v);
    w = get<0>(v); // same effect as the previous line
    w = v; // same effect as the previous line

//  std::get<double>(v); // error: no double in [int, float]
//  std::get<3>(v);      // error: valid index values are 0 and 1

    try
    {
        get<float>(w); // w contains int, not float: will throw
    }
    catch (const bad_variant_access& ex)
    {
        std::cout << ex.what() << '\n';
    }

    using namespace std::literals;

    variant<std::string> x("abc");
    // converting constructors work when unambiguous
    x = "def"; // converting assignment also works when unambiguous

    variant<std::string, void const*> y("abc");
    // casts to void const * when passed a char const *
    assert(holds_alternative<void const*>(y)); // succeeds
    y = "xyz"s;
    assert(holds_alternative<std::string>(y)); // succeeds
}
